package eclipse.lib.scripting;
import eclipse.*;
/**
 * The ByteInterpreter class contains all the necessary static methods for the modification of an arrya of bytes.
 */
public class ByteInterpreter 
{
	/**
	 * Creates a 16bit byte array from a 16bit character
	 * @param cChar Character to convert
	 */
	public static byte[] charToByteArray(char cChar) 
	{
		return new byte[] {
			(byte)((cChar >> 8) & 0xff),
			(byte)((cChar >> 0) & 0xff),
		};
	}
	/**
	 * Creates an 8bit byte array from a boolean
	 * @param bBoolean Boolean to convert
	 */
	public static byte[] booleanToByteArray(boolean bBoolean) 
	{
		return new byte[]{(byte)(bBoolean ? 0x01 : 0x00)};
	}
	/**
	 * Creates a 32bit byte array from an integer
	 * @param int32 Integer to convert
	 */
	public static byte[] intToByteArray(int int32) 
	{	
		return new byte[] {
			(byte)((int32 >> 24) & 0xff), 
			(byte)((int32 >> 16) & 0xff), 
			(byte)((int32 >> 8) & 0xff),
			(byte)((int32 >> 0) & 0xff),
		};
	}
	/**
	 * Creates a 32bit byte array from a float
	 * @param fInt32 Float to convert
	 */
	public static byte[] floatToByteArray(float fInt32)
	{
		return intToByteArray(Float.floatToRawIntBits(fInt32));
	}
	/**
	 * Creates a 64bit byte array from a long
	 * @param int64 Long to convert
	 */
	public static byte[] longToByteArray(long int64)
	{
		return new byte[] {
			(byte)((int64 >> 56) & 0xff),
			(byte)((int64 >> 48) & 0xff),
			(byte)((int64 >> 40) & 0xff),
			(byte)((int64 >> 32) & 0xff),
			(byte)((int64 >> 24) & 0xff),
			(byte)((int64 >> 16) & 0xff),
			(byte)((int64 >> 8)  & 0xff),
			(byte)((int64 >> 0)  & 0xff)
		};
	}
	/**
	 * Creates a 64bit byte array from a double
	 * @param fInt64 Double to convert
	 */
	public static byte[] doubleToByteArray(double fInt64)
	{
		return longToByteArray(Double.doubleToRawLongBits(fInt64));
	}
	/**
	 * Creates a byte array from a String
	 * @param sString String to convert
	 */
	public static byte[] stringToByteArray(String sString) 
	{
		return (sString == null) ? null : sString.getBytes();
	}
	/**
	 * Creates a Char from a byte array
	 * @param byteArray Array of bytes to convert
	 */
	public static char byteArrayToChar(byte[] byteArray)
	{
		return (char)((0xff & byteArray[0]) << 8 |(0xff & byteArray[1]) << 0);
	}
	/**
	 * Creates a Char array from a byte array
	 * @param byteArray Array of bytes to convert
	 */
	public static char[] byteArrayToCharArray(byte[] byteArray)
	{
		int size 			= byteArray.length / 2;
		char[] charArray 	= new char[size];
		byte[] tmpArray;
		for(int s = 0; s < size; s++)
		{
			tmpArray = ByteInterpreter.getSubByteArray(byteArray, s * 2, (s + 1) * 2);
			charArray[s] = byteArrayToChar(tmpArray);
		}
		return charArray;
	}
	/**
	 * Creates a byte array from a Char array
	 * @param charArray Array of characters to convert
	 */
	public static byte[] charArrayToByteArray(char[] charArray)
	{
		byte[] byteArray	= new byte[charArray.length * 2];
		byte[] tmpArray;
		for(int s = 0; s < charArray.length; s++)
		{
			tmpArray = ByteInterpreter.charToByteArray(charArray[s]);
			byteArray = ByteInterpreter.appendToByteArray(byteArray, tmpArray, s * 2);
		}
		return byteArray;
	}
	/**
	 * Creates an Integer from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static int byteArrayToInt(byte[] byteArray, int offset)
	{
		return
			(0xff & byteArray[offset])		<< 24 | 
			(0xff & byteArray[offset + 1]) 	<< 16 | 
			(0xff & byteArray[offset + 2])	<< 8  | 
			(0xff & byteArray[offset + 3]) 	<< 0;
	}
	/**
	 * Creates a float from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static float byteArrayToFloat(byte[] byteArray, int offset)
	{
		return Float.intBitsToFloat(byteArrayToInt(byteArray, offset));
	}
	/**
	 * Creates a long from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static int byteArrayToLong(byte[] byteArray, int offset)
	{
		return
			(0xff & byteArray[offset])		<< 56 |
			(0xff & byteArray[offset + 1])	<< 48 |
			(0xff & byteArray[offset + 2])	<< 40 |
			(0xff & byteArray[offset + 3])	<< 32 |
			(0xff & byteArray[offset + 4])  << 24 |
			(0xff & byteArray[offset + 5])  << 16 |
			(0xff & byteArray[offset + 6])	<< 8  |
			(0xff & byteArray[offset + 7])  << 0;
	}
	/**
	 * Creates a double from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static double byteArrayToDouble(byte[] byteArray, int offset)
	{
		return Double.longBitsToDouble(byteArrayToLong(byteArray, offset));
	}
	/**
	 * Creates a String from a byte array
	 * @param byteArray Byte array to convert
	 */
	public static String byteArrayToString(byte[] byteArray) 
	{
		return new String(byteArray);
	}
	/**
	 * Adds a byte array to another byte array
	 * @param dArray Array to append to
	 * @param sArray Array to append
	 * @param offset Offset to start appending
	 */
	public static byte[] appendToByteArray(byte[] dArray, byte[] sArray, int offset)
	{
		for(int i = 0; i < sArray.length; i++)		
			dArray[offset + i] = sArray[i];		
		return dArray;
	}
	/**
	 * Adds a byte array to the end of a byte array
	 * @param dArray Byte array to append to
	 * @param sArray Byte array to append
	 */
	public static byte[] appendToByteArray(byte[] dArray, byte[] sArray)
	{
		int endOfArray = dArray.length;
		if(endOfArray < endOfArray + sArray.length)
			dArray = expandByteArray(dArray, sArray.length);
		for(int i = 0; i < sArray.length; i++)
			dArray[endOfArray + i] = sArray[i];
		return dArray;			
	}
	/**
	 * Returns a byte array from another byte array
	 * @param byteArray Byte array to parse
	 * @param offset_START Starting location
	 * @param offset_END Ending location
	 */
	public static byte[] getSubByteArray(byte[] byteArray, int offset_START, int offset_END)
	{
		byte[] byteBuffer = new byte[offset_END - offset_START];
		for(int i = offset_START; i < offset_END; i++)		
			byteBuffer[i - offset_START] = byteArray[i];	
		return byteBuffer;
	}
	/**
	 * Extends the maximum size of a byte array
	 * @param byteArray Byte array to expand
	 * @param appendLength Size to extend array
	 * @return
	 */
	public static byte[] expandByteArray(byte[] byteArray, int appendLength)
	{
		byte[] cArray = byteArray.clone();		
		byteArray = new byte[cArray.length + appendLength];
		for(int i = 0; i < cArray.length; i++)
			byteArray[i] = cArray[i];
		return byteArray;
	}
	/**
	 * Compares to byte arrays
	 * @param array1 Array 1 
	 * @param array2 Array 2
	 */
	public static boolean compareByteArray(byte[] array1, byte[] array2)
	{
		if(array1.equals(array2))
			return true;
		else
			return false;
	}
	/**
	 * Converts a String to an array of Char
	 * @param sVal String to convert
	 */
	public static char[] stringToCharArray(String sVal)
	{		
		return sVal.toCharArray();
	}
	/**
	 * Converts an array of Char to a String
	 * @param charArray Array of Chars to convert
	 */
	public static String charArrayToString(char[] charArray)
	{
		return new String(charArray);
	}
	/**
	 * Converts an Integer to a 4byte String
	 * @param val Integer to convert
	 */
	public static String appendIntegerToString(int val)
	{
		byte[] comCode = 	ByteInterpreter.intToByteArray(val);
		char[] chrCode = 	ByteInterpreter.byteArrayToCharArray(comCode);
		return 				ByteInterpreter.charArrayToString(chrCode);
	}
	/**
	 * Converts a float to a 4byte String
	 * @param val float to convert
	 */
	public static String appendFloatToString(float val)
	{
		byte[] comCode = 	ByteInterpreter.floatToByteArray(val);
		char[] chrCode = 	ByteInterpreter.byteArrayToCharArray(comCode);
		return				ByteInterpreter.charArrayToString(chrCode);
	}	
	/**
	 * Returns an Integer from a String
	 * @param val String to parse
	 * @param offset Offset to start parsing
	 */
	public static int getIntFromString(String val, int offset)
	{
		char[] chrCode = new char[Constants.CHARSIZE];
		byte[] comCode;
		
		val.getChars(offset, offset + Constants.CHARSIZE, chrCode, 0);
		comCode = ByteInterpreter.charArrayToByteArray(chrCode);
		return ByteInterpreter.byteArrayToInt(comCode, 0);
	}
	/**
	 * Returns a float from a String
	 * @param val String to parse
	 * @param offset Offset to start parsing
	 */
	public static float getFloatFromString(String val, int offset)
	{
		char[] chrCode = new char[Constants.CHARSIZE];
		byte[] comCode;
		
		val.getChars(offset, offset + Constants.CHARSIZE, chrCode, 0);
		comCode = ByteInterpreter.charArrayToByteArray(chrCode);
		return ByteInterpreter.byteArrayToFloat(comCode, 0);
	}
}
